#!/usr/bin/python           # This is client.py file
import wx
from twisted.internet import wxreactor
from common.cred import Credentials
wxreactor.install()

from twisted.internet import reactor, protocol
from twisted.protocols import basic

import time
import cPickle
from common.deck import *
from common.card import *
from common.hand import *
from common.message import Message
from cPlayer import cPlayer
from cDealer import cDealer


class LoginDialog(wx.Dialog):
    '''
    Pop up panel for collecting user credentials and logging into the netjack server.
    '''    
    
    def __init__(self, *args, **kw):
        super(LoginDialog, self).__init__(*args, **kw)
        
        self.InitUI()
        self.SetSize((200,150))
        self.SetTitle("Login to NetJack")
        
    def InitUI(self):
        pnl = wx.Panel(self)
        vbox = wx.BoxSizer(wx.VERTICAL)
        
        sb = wx.StaticBox(pnl, label="Login")
        sbs = wx.StaticBoxSizer(sb, orient=wx.VERTICAL)
        self.usernameTxt = wx.TextCtrl(pnl, size=(150, 20))
        self.passwordTxt = wx.TextCtrl(pnl, size=(150, 20), style=wx.TE_PASSWORD) 
        sbs.Add(self.usernameTxt)
        sbs.Add(self.passwordTxt)
        
        pnl.SetSizer(sbs)
        
        hbox2 = wx.BoxSizer(wx.HORIZONTAL)
        loginButton = wx.Button(self, label='Login')
        closeButton = wx.Button(self, label='Cancel')
        hbox2.Add(loginButton)
        hbox2.Add(closeButton, flag=wx.LEFT, border=5)

        vbox.Add(pnl, proportion=1, 
            flag=wx.ALL|wx.EXPAND, border=5)
        vbox.Add(hbox2, 
            flag=wx.ALIGN_CENTER|wx.TOP|wx.BOTTOM, border=10)

        self.SetSizer(vbox)
        
        loginButton.Bind(wx.EVT_BUTTON, self.OnLogin)
        closeButton.Bind(wx.EVT_BUTTON, self.OnClose)
        
    def OnClose(self, e):
        self.Destroy()
    
    def OnLogin(self, e):
        '''
        Create an AUTH_INIT message with current credentials and send to server.
        '''
        username = self.usernameTxt.Value
        password = self.passwordTxt.Value
        cred = Credentials(username, password)
        msg = Message(msg_type=defines.AUTH_INIT, player_id=self.Parent.player.id, payload=cred)
        self.Parent.protocol.sendLine(cPickle.dumps(msg))
        
        
class NetJackFrame(wx.Frame):
    
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title=title, style=wx.DEFAULT_FRAME_STYLE & ~ (wx.RESIZE_BORDER | wx.RESIZE_BOX | wx.MAXIMIZE_BOX), size=(800,650))
        self.InitUI()
        
    def InitUI(self):    
        
        ID_LOGIN = wx.NewId()
        
        #Load BMP Resources
        self.deck_sprite = wx.Bitmap('resources/52_100.png')
        self.felt = wx.Bitmap('resources/felt.png')
        wx.EVT_PAINT(self, self.OnPaint)
        
        self.Center()
        self.CreateStatusBar()
        
        #setting up the menus
        filemenu = wx.Menu()
        
        filemenu.Append(ID_LOGIN, "&Login", "Login to NetJack")
        filemenu.AppendSeparator()
        filemenu.Append(wx.ID_EXIT, "E&xit", " Terminate the program")
        
        #Create the menubar
        menuBar = wx.MenuBar()
        menuBar.Append(filemenu, "&NetJack")
        self.SetMenuBar(menuBar)
        

        #Main GUI --Static Layout
        self.table = wx.Panel(self, size=(800, 400))
        self.text = wx.TextCtrl(self, style=wx.TE_MULTILINE | wx.TE_READONLY, pos=(400,400), size=(400,175))
        self.ctrl = wx.TextCtrl(self, style=wx.TE_PROCESS_ENTER, pos=(400, 575),size = (400, 25))
        self.dealCardBtn = wx.Button(self, pos=(0,400), size = (100,25), label="Hit Me!")
        
        
        #Event Bindings
        self.ctrl.Bind(wx.EVT_TEXT_ENTER, self.broadcastChat)
        self.dealCardBtn.Bind(wx.EVT_BUTTON, self.hitMe)
        self.Bind(wx.EVT_MENU, self.OnLoginMenu, id=ID_LOGIN)
        
        self.player = cPlayer()
        self.players = {}
        self.dealer = cDealer()
    
    def hitMe(self, evt):
        '''
        Request card from dealer
        '''
        msg = Message(defines.MSG_ACTION, self.player.id, defines.ACTION_HITME)
        self.protocol.sendLine(cPickle.dumps(msg))
    
    def broadcastChat(self, evt):
        
        #Pass contents of textbox to the twisted protocol wrapped as s pickled message object.
        msg = Message(defines.MSG_CHAT_BROADCAST, self.player.id, self.ctrl.GetValue())
        self.protocol.sendLine(cPickle.dumps(msg))
        self.ctrl.SetValue("")
        
    def OnPaint(self, event):
        
        #Render Table Panel
        dc = wx.PaintDC(self.table)
        dc.DrawBitmap(self.felt, 0, 0)
        try:
            #Render Dealer
            self.dealer.render_hand(dc, self.deck_sprite)
            
            #Render Player
            self.player.render_hand(dc, self.deck_sprite)
            
            #Render other players
            for other_player in self.players.itervalues():
                other_player.render_hand(dc, self.deck_sprite)
            
        except Exception, ex:
            print ex
        
        #Render the rest of the window
        dc = wx.PaintDC(self)

    def OnLoginMenu(self, e):
        self.login = LoginDialog(self, title="Login to NetJack")
        self.login.ShowModal()
        self.login.Destroy()

class DataForwardingProtocol(basic.LineReceiver):
    def __init__(self):
        self.output = None
        
    def dataReceived(self, data):
        gui = self.factory.gui
        
        gui.protocol = self
        
        if gui:
            try:
                msg = cPickle.loads(data)
                
                #INITIALIZE PLAYER
                if msg.msg_type == defines.PLAYER_INIT:
                    gui.player.id =msg.player_id
                    
                elif msg.msg_type == defines.AUTH_USER_AUTHENTICATED:
                    gui.player.bank = msg.payload['balance']
                    gui.player.name = msg.payload['name']
                    hand = msg.payload['hand']
                    gui.player.new_hand(hand[0], hand[1])
                    gui.login.Hide()
                    gui.login.Destroy()
                    gui.Refresh()
                    
                elif msg.msg_type == defines.AUTH_USER_NOT_AUTHENTICATED:
                    pass
                                
                elif msg.msg_type == defines.OBJ_CARD:
                    card = msg.payload
                    gui.player.hit(card)
                    gui.Refresh()
                    
                elif msg.msg_type == defines.MSG_CHAT_BROADCAST:
                    val = gui.text.GetValue()
                    gui.text.SetValue(val + msg.payload + '\n')
                    gui.text.SetInsertionPointEnd()
                
                else:
                    pass
                
            except Exception, ex:
                print ex
    
    def connectionMade(self):
        self.output = self.factory.gui.text

class ChatFactory(protocol.ClientFactory):
    
    def __init__(self, gui):
        self.gui = gui
        self.protocol = DataForwardingProtocol
        
    def clientConnectionLost(self, transport, reason):
        reactor.stop()
        
    def clientConnectionFailed(self, transport, reason):
        reactor.stop()
        
class MyApp(wx.App):
    def OnInit(self):
        login_name = "Dave Matthews"
        frame = NetJackFrame(None, -1, login_name)
        frame.Show(True)
        self.SetTopWindow(frame)
        reactor.registerWxApp(self)
        reactor.connectTCP("localhost", 5001, ChatFactory(frame))  
        reactor.run()
       
        
        return True

   
app = MyApp(0)